import datetime

from flask import render_template, g, abort, request, current_app, jsonify, redirect, url_for

from ihome import db, sr
from ihome.models import House, Area, Facility, HouseImage, Order
from ihome.modules.api import api_blu
from ihome.utils.common import user_login_data, upload_file
from ihome.utils.constants import QINIU_DOMIN_PREFIX, HOUSE_LIST_PAGE_CAPACITY

from ihome.utils.response_code import RET, error_map


# 我的房屋发布列表
@api_blu.route('/user/houses')
@user_login_data
def user_houses():
    user = g.user
    if not user:  # 用户未登录, 重定向到前台首页
        return redirect(url_for("html.index"))

    # 数据库行为: 分页查询当前用户发布的所有房屋
    data = []
    try:
        my_houses = House.query.filter(House.user_id == user.id).all()
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    if my_houses:
        data = [house.to_basic_dict() for house in my_houses]
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK], data= data)


# 城区列表
@api_blu.route('/areas')
def areas():
    try:
        areas = Area.query.all()
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK], data=[area.to_dict() for area in areas])


# 发布房源
@api_blu.route('/houses', methods=["POST"])
@user_login_data
def houses():
    user = g.user
    if not user:  # 用户未登录, 重定向到前台首页
        return redirect(url_for("html.index"))

    # 获取参数
    user_id = user.id
    title = request.json.get('title')
    price = request.json.get('price')
    area_id = request.json.get('area_id')
    address = request.json.get('address')
    room_count = request.json.get('room_count')
    acreage = request.json.get('acreage')
    unit = request.json.get('unit')
    capacity = request.json.get('capacity')
    beds = request.json.get('beds')
    deposit = request.json.get('deposit')
    min_days = request.json.get('min_days')
    max_days = request.json.get('max_days')
    facility_list = request.json.get("facility")
    # 校验参数
    if not all([title, price, area_id, address, room_count, acreage, unit, capacity, beds, deposit, min_days, max_days, facility_list]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    try:
        user_id = int(user_id)
        area_id = int(area_id)
        room_count = int(room_count)
        acreage = int(acreage)
        capacity = int(capacity)
        min_days = int(min_days)
        max_days = int(max_days)
    except BaseException as e:
        current_app.logger.error(e)
        jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 数据库行为: 添加房源信息
    try:
        house = House()
        house.user_id = user_id
        house.title = title
        house.price = price
        house.area_id = area_id
        house.address = address
        house.room_count = room_count
        house.acreage = acreage
        house.unit = unit
        house.capacity = capacity
        house.beds = beds
        house.deposit = deposit
        house.min_days = min_days
        house.max_days = max_days
        house.facilities = Facility.query.filter(Facility.id.in_(facility_list)).all()

    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    # 添加到事务中
    db.session.add(house)
    try:
        db.session.commit()
    except BaseException as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    data = {"house_id": house.id}
    # 返回 json 结果
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK], data=data)

# 上传房屋图片
@api_blu.route('/houses/<int:house_id>/images', methods=['POST'])
@user_login_data
def upload_image(house_id):
    # 判断用户是否存在
    user = g.user
    if not user:
        return  jsonify(errno=RET.SESSIONERR,errmsg=error_map[RET.SESSIONERR])

    # 获取参数
    house_image = request.files.get('house_image')

    try:
        house = House.query.get(house_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    # 校验参数
    if not house_image:
        return  jsonify(errno=RET.PARAMERR,errmsg=error_map[RET.PARAMERR])

    # 将图片上传并将链接添加到数据库
    try:
        house_image_bytes = house_image.read()
        house_image_url = upload_file(house_image_bytes)
    except BaseException as e:
        current_app.logger.error(e)
        return  jsonify(errno=RET.THIRDERR,errmsg=error_map[RET.THIRDERR])

    # 将图片存在数据库中
    try:
        image = HouseImage()
        if not house.index_image_url:
            house.index_image_url = house_image_url
        image.house_id = house_id
        image.url = house_image_url
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    db.session.add(image)
    try:
        db.session.commit()
    except BaseException as e:
        current_app.logger.error(e)
        return  jsonify(errno=RET.DBERR,errmsg=error_map[RET.DBERR])

    data = {
        "url": QINIU_DOMIN_PREFIX + image.url
    }


    # 返回
    return  jsonify(errno=RET.OK,errmsg=error_map[RET.OK],data=data)


# 房屋详情页
@api_blu.route('/houses/<int:house_id>')
@user_login_data
def houses_details(house_id):
    user = g.user
    if not user:
        user_id = -1
    else:
        user_id = user.id

    # 查询某条房屋的数据  根据house_id
    try:
        house = House.query.get(house_id)
        # house = House.query.filter(House.id ==house_id).first()
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    if not houses:
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    try:
        user_id = int(user_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    data={
        "house":house.to_full_dict(),
        "user_id":user_id
    }
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK],data = data)


# 首页房屋推荐展示
@api_blu.route('/houses/index')
def houses_index():
    # 数据库查询
    try:
        houses = House.query.all()
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    data_list = []
    for house in houses:
        house_imgs_url = []
        for imge in house.images:
            if imge:
                house_imgs_url.append(imge.url)

        data_dict = {
            "house_id": house.id,
            "img_url": QINIU_DOMIN_PREFIX + house_imgs_url[0],
            "title": house.title
        }

        data_list.append(data_dict)
        data_list = data_list[0:5]


    # 返回结果
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK
    ], data=data_list)


# 房屋数据搜索
@api_blu.route('/houses')
def houses_search():
    # 获取参数
    aid = request.args.get('aid', '')
    start_day = request.args.get('sd', '')
    end_day = request.args.get('ed', '')
    sort_key = request.args.get('sk', 'new')
    # 排序方式booking(订单量), price - inc(低到高), price - des(高到低)
    page = request.args.get('p', '1')

    # 参数校验
    try:
        page = int(page)
        print(page)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 日期转换
    try:
        start_data = None
        end_data = None
        if start_day:
            start_data = datetime.datetime.strptime(start_day, "%Y-%m-%d")
        if end_day:
            end_data = datetime.datetime.strptime(end_day, "%Y-%m-%d")
        if start_data and end_data:
            assert start_data < start_data ,Exception("开始时间大于结束时间")
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    try:
        redis_key = "houses_%s_%s_%s_%s"%(start_day, end_day, aid, sort_key)
        response_data = sr.hget(redis_key, page)
        if response_data:
            return jsonify(errno=RET.OK, errmsg=error_map[RET.OK], data=eval(response_data))
    except BaseException as e:
        current_app.logger.error(e)

    # 按照条件查询数据
    house_list = list()
    if aid: # 判断是否传入城区ID
        house_list.append(House.area_id == aid)

    # 过滤预定的房屋
    conflict_order =None
    try:
        if start_data and end_data:
            conflict_order = Order.query.filter(Order.begin_date<= end_data,Order.end_date>=start_data).all()
        elif start_data:
            conflict_order = Order.query.filter(Order.end_date >= start_data).all()
        elif end_data:
            conflict_order = Order.query.filter(Order.begin_date <= end_data).all()
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])

    # 冲突订单的房屋ID
    if conflict_order:
        conflict_houses_id = [order.house_id for order in conflict_order]
        # 查询不包括冲突订单的ID
        house_list.append(House.id not in conflict_houses_id)

    # 条件查询
    if sort_key == 'booking':
        house_query = House.query.filter(*house_list).order_by(House.orders.desc())
    elif sort_key == 'price-inc':
        house_query =House.query.filter(*house_list).order_by(House.price)
    elif sort_key == 'price-des':
        house_query =House.query.filter(*house_list).order_by(House.price.desc())
    else:
        house_query =House.query.filter(*house_list).order_by(House.create_time.desc())

    # 分页查询
    pn = house_query.paginate(page, HOUSE_LIST_PAGE_CAPACITY,False)
    # # 当前页的房屋信息
    # houses = pn.items
    # # 总页数
    # total_page = pn.pages


    data = {
        "houses": [house.to_basic_dict() for house in pn.items],
        "total_page": pn.pages
    }

    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK], data=data)
